package controller

import (
	. "gddgame.cc/galaxy/common/dsl/game/ad"
	. "gddgame.cc/galaxy/common/dsl/game/reward"
	. "gddgame.cc/galaxy/common/dsl/game/user"
	. "gddgame.cc/galaxy/common/dsl/web"
	"gddgame.cc/galaxy/common/namespaces/cooperate"
	"gddgame.cc/galaxy/project/breeder/breeder/center"
	"gddgame.cc/galaxy/project/breeder/breeder/cooperated"
	"gddgame.cc/galaxy/project/breeder/breeder/model"
	"gddgame.cc/galaxy/utils"
	"gddgame.cc/galaxy/utils/orm"

	"gddgame.cc/galaxy/utils/def"
)

func GetUser(context def.Context, userId int) (*model.User, error) {
	var user model.User
	if err := Center.GetUser(userId, &user); err != nil {
		return nil, SystemExceptionDetail("更新失败", err)
	}
	return &user, nil
}

func GetUserByAccount(context def.Context, accountId int) (*model.User, error) {
	var user model.User

	err := Center.GetUser(accountId, &user)
	if err != nil || user.AccountId != accountId {
		if ok, err := model.UserModel.Query().Where("=", "account_id", accountId).One(&user); !ok {
			return nil, EmptyExceptionDetail("USER_NOEXIST", err)
		}
	}
	return &user, nil
}

func GetUserPublicInfo(context def.Context, user *model.User, language string) (*model.GameOtherUserExtend, error) {
	// 账号信息，等级信息，属性信息
	data := &model.GameOtherUserExtend{}
	data.IsSystem = user.IsSystem
	return data, nil
}

func GetUserDetailInfo(context def.Context, user *model.User, account *cooperated.Account, statData map[string]int32) (*model.GameUserExtend, error) {
	props := map[string]int{}
	uProps, err := GetProps(context, user.Id, nil)
	if err == nil {
		for _, p := range uProps {
			props[utils.ToString(p.PropId)] = p.Number
		}
	}
	userData := map[string]int{}
	for _, item := range Center.RelationMap[utils.ToString(model.UserType)] {
		value, ok := account.PropInstance.GetProp2(item.Key)
		if !ok {
			value, err = user.Get(user, item.Key)
			if err != nil {
				value = account.AbilityProp.GetAttrWithKey(item.Key)
			} else {
				value = utils.ToInt(value)
			}
		}
		value, err := user.Schema.Get(user, item.Key)
		if err != nil {
			continue
		}
		userData[utils.ToString(item.Id)] = utils.ToInt(value)
	}
	extend := &model.GameUserExtend{
		Title:   "",
		Science: utils.MapIntToString(user.Sciences),
		Data:    userData,
		Total:   statData,
		Props:   props,
	}

	return extend, nil
}

func ReceiveReward(context def.Context, user *model.User, reward *GoldReward, data map[string]interface{}) error {

	return nil
}

func ReceiveRewardMessage(context def.Context, user *model.User, messageId int) (*GoldReward, error) {
	message, err := Center.GetMessage(user.Id, messageId)
	if err != nil {
		return nil, err
	}
	_ = Center.ReadMessage(user.Id, messageId)
	data := map[string]interface{}{}
	gold := GoldRewardFromReward(&message.Reward)
	if t, err := NextAd(Env, user.OpenId, model.SingleAdPlane); err == nil {
		if t.Ok() {
			_ = UpdateAd(Env, user.OpenId, t)
			gold.Gold = gold.Gold * 3
		}
	}
	switch message.Type {
	}
	if err := ReceiveReward(context, user, gold, data); err != nil {
		return nil, err
	}
	if err := Center.UpdateUser(user, data); err != nil {
		return nil, err
	}
	return gold, nil
}

func SendShareMessage(context def.Context, userId int, target string, nickName string) (*UserMessage, error) {
	message := &UserMessage{
		UserId:   userId,
		Type:     model.ShareMessage,
		TargetId: target,
		Status:   false,
		Content: map[string]string{
			"nick_name": nickName,
		},
		Reward: model.DefaultShareReward,
	}
	if err := Center.SendMessage(message); err != nil {
		return nil, err
	}
	return message, nil
}

func SendAchievementMessage(context def.Context, userId int, achievementId int, reward *Reward) (*UserMessage, error) {
	message := &UserMessage{
		UserId:   userId,
		Type:     model.AchievementMessage,
		TargetId: utils.ToString(achievementId),
		Status:   false,
		Content:  map[string]string{},
		Reward:   *reward,
	}
	if err := Center.SendMessage(message); err != nil {
		return nil, err
	}
	return message, nil
}

func UpdateStatus(context def.Context, oldStatus bool, status bool) error {
	if _, err := model.UserModel.Query().Where("=", "status", oldStatus).Update(map[string]interface{}{
		"status": status,
	}); err != nil {
		return SystemExceptionDetail("更新状态失败", err)
	}
	return nil
}

func ValidRequire(context def.Context, require *model.Require, user *model.User, account cooperate.PropsInstance, userUnit *model.UserUnit, owner cooperate.PropsInstance) bool {
	//var err error
	if require.Sciences != nil && len(require.Sciences) > 0 {
		if user == nil {
			return false
		}
		for id, compare := range require.Sciences {
			if !compare.Valid(user.Sciences[id]) {
				return false
			}
		}
	}
	if require.User != nil && len(require.User) > 0 {
		if user == nil {
			return false
		}
		if account == nil {
			return false
		}
		for id, compare := range require.User {
			item := Center.RelationGroupMap[id]
			v, err := user.Get(user, item.Key)
			if err != nil {
				if account != nil {
					v = account.AttrWithKey(item.Key)
					err = nil
				} else {
					return false
				}
			}
			if !compare.Valid(utils.ToInt(v)) {
				return false
			}
		}
	}
	if require.Owner != nil && len(require.Owner) > 0 {
		if owner != nil {
			for id, compare := range require.Owner {
				item := Center.RelationGroupMap[id]
				// 从数据中->属性中->
				value, ok := owner.GetProp2(item.Key)
				if !ok {
					value = owner.AttrWithKey(item.Key)
				}
				if !compare.Valid(utils.ToInt(value)) {
					return false
				}
			}
		}
	}
	if require.Powers != nil && len(require.Powers) > 0 {
		var info map[int]int
		if userUnit == nil {
			return false
		}
		info = userUnit.Powers
		for id, compare := range require.Powers {
			if info == nil || !compare.Valid(info[id]) {
				return false
			}
		}
	}
	return true
}

func ValidConsume(context def.Context, consume *model.Consume, number int, user *model.User, userUnit *model.UserUnit) (bool, *center.ConsumeData) {
	consumeData := &center.ConsumeData{}
	if consume == nil {
		return true, consumeData
	}
	var err error
	if consume.User != nil {
		consumeData.UserData = map[string]interface{}{}
		for id, value := range consume.User {
			item := Center.RelationGroupMap[id]
			v, err := user.Get(user, item.Key)
			if err != nil {
				return false, nil
			}
			if utils.ToInt(v) < value*number {
				return false, nil
			}
			consumeData.UserData[item.Key] = &orm.UpdateOperate{Operate: "-", Value: value * number}
		}
	}

	if consume.Owner != nil {
		consumeData.UserUnitData = map[string]interface{}{}
		for id, value := range consume.Owner {
			item := Center.RelationGroupMap[id]
			v, err := userUnit.Get(userUnit, item.Key)
			if err != nil {
				return false, nil
			}
			if utils.ToInt(v) < value*number {
				return false, nil
			}
			consumeData.UserUnitData[item.Key] = &orm.UpdateOperate{Operate: "-", Value: value * number}
		}
	}

	if consume.Props != nil {
		consumeData.UserProps, err = ValidProps(context, consume.Props, number, user)
		if err != nil {
			return false, nil
		}
	}

	return true, consumeData
}

func UpdateConsume(context def.Context, consumeData *center.ConsumeData, user *model.User, userUnit *model.UserUnit) error {
	if consumeData.UserProps != nil && len(consumeData.UserProps) > 0 {
		if err := RemoveProps(context, consumeData.Consume.Props, consumeData.Number, consumeData.UserProps); err != nil {
			return err
		}
	}
	if consumeData.UserData != nil && len(consumeData.UserData) > 0 {
		if err := Center.UpdateUser(user, consumeData.UserData); err != nil {
			return err
		}
	}
	if consumeData.UserUnitData != nil && len(consumeData.UserUnitData) > 0 {
		if err := UpdateUnit(context, userUnit, consumeData.UserUnitData); err != nil {
			return err
		}
	}
	return nil
}

func UpdateReceive(context def.Context, receive *model.Receive, number int, user *model.User) bool {
	if receive.Props != nil {
		if err := AddProps(context, receive.Props, number, user); err != nil {
			return false
		}
	}
	if receive.Equips != nil {
		if err := AddEquips(context, receive.Equips, number, user); err != nil {
			return false
		}
	}
	if receive.User != nil {
		userData := map[string]interface{}{}

		for id, value := range receive.User {
			item := Center.RelationGroupMap[id]
			userData[item.Key] = &orm.UpdateOperate{Operate: "+", Value: value * number}
		}
		if err := Center.UpdateUser(user, userData); err != nil {
			// todo 还原道具
			return false
		}
	}
	return true
}

func ValidUpgradeBuild(context def.Context, buildLevel int, buildId int, user *model.User, account *cooperated.Account, build *cooperated.Build) error {
	buildInfo, ok := Center.BuildMap[buildId]
	if !ok {
		return ValidException("建筑类型错误")
	}
	if buildLevel+1 >= len(buildInfo.Levels) {
		return ValidException("建筑已是最高级")
	}
	levelInfo := buildInfo.Levels[buildLevel]
	if !ValidRequire(context, levelInfo.RequireSlice, user, account, nil, build) {
		return ValidException("不满足升级条件")
	}
	if ok, consumeData := ValidConsume(context, levelInfo.ConsumeSlice, 1, user, nil); !ok {
		return ValidException("升级所需不足")
	} else {
		if err := UpdateConsume(context, consumeData, user, nil); err != nil {
			return err
		}
	}
	return nil
}

func ValidCreateBuild(context def.Context, buildId int, user *model.User, account cooperate.PropsInstance, creater cooperate.PropsInstance, needConsume bool) error {
	buildInfo, ok := Center.BuildMap[buildId]
	if !ok {
		return ValidException("建筑类型错误")
	}
	var userUnit *model.UserUnit
	var err error
	if creater.GetDataType() == cooperated.UnitType {
		if !buildInfo.CanUnit {
			return ValidException("建筑对象错误")
		}
		userUnitId := utils.ToString(creater.GetId())

		userUnit, err = GetUnitWithUser(context, userUnitId, user)
		if err != nil {
			return err
		}
	}

	// 获取上一级设置
	levelInfo := buildInfo.Levels[0]
	if !ValidRequire(context, levelInfo.RequireSlice, user, account, userUnit, creater) {
		return ValidException("不满足建造条件")
	}
	if ok, consumeData := ValidConsume(context, levelInfo.ConsumeSlice, 1, user, nil); !ok {
		return ValidException("建筑所需不足")
	} else {
		// 在建造后再执行消耗
		if needConsume {
			if err := UpdateConsume(context, consumeData, user, nil); err != nil {
				return err
			}
		}
	}

	return nil
}
